/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.services.system;

import cn.easyplatform.ServiceException;
import cn.easyplatform.dao.DaoFactory;
import cn.easyplatform.dao.EntityDao;
import cn.easyplatform.entities.EntityInfo;
import cn.easyplatform.entities.beans.ResourceBean;
import cn.easyplatform.entities.transform.TransformerFactory;
import cn.easyplatform.i18n.I18N;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.lang.stream.StringOutputStream;
import cn.easyplatform.services.AbstractService;
import cn.easyplatform.services.IDataSource;
import cn.easyplatform.services.SystemServiceId;
import cn.easyplatform.type.EntityType;
import cn.easyplatform.type.StateType;
import org.apache.shiro.config.Ini.Section;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class EntitiesDataSourceSevice extends AbstractService implements IDataSource {

    private DataSourceService delegate;


    @Override
    public String getId() {
        return delegate.getId();
    }

    @Override
    public String getName() {
        return delegate.getName();
    }

    @Override
    public String getDescription() {
        return delegate.getDescription();
    }

    @Override
    public void start() throws ServiceException {
        if (getState() != StateType.STOP)
            return;
        Section section = engineConfiguration.getAttributes("entities");
        ResourceBean bean = null;
        if (section == null) {// 如果没有配置参数连接，使用本地derby服务
            section = engineConfiguration.getAttributes("derby");
            if (section == null)
                throw new ServiceException(
                        I18N.getLabel("easyplatform.sys.cl.config"));
            bean = new ResourceBean();
            bean.setId(SystemServiceId.SYS_ENTITY_DS);
            bean.setDescription(I18N.getLabel("easyplatform.sys.cl.desp"));
            bean.setName(I18N.getLabel("easyplatform.sys.cl.name"));
            bean.setType(EntityType.DATASOURCE.getName());
            bean.setProps(new HashMap<String, String>());
            StringBuilder sb = new StringBuilder();
            sb.append("jdbc:derby:");
            if (section.get("derby.database.name") != null)
                sb.append(section.get("derby.database.name"));
            else
                sb.append("easyplatform-entities");
            sb.append(";create=false");
            bean.getProps().put("jdbcUrl", sb.toString());
            if (section.get("derby.user.name") != null)
                bean.getProps().put("username", section.get("derby.user.name"));
            if (section.get("derby.user.password") != null)
                bean.getProps().put("password",
                        section.get("derby.user.password"));
            bean.getProps().put("driverClassName",
                    "org.apache.derby.jdbc.EmbeddedDriver");
            bean.getProps().put("initialSize", "5");
            bean.getProps().put("maxActive", "10");
            bean.getProps().put("minIdle", "1");
            bean.getProps().put("useUnfairLock", "true");
            bean.getProps().put("poolPreparedStatements", "false");
            bean.getProps().put("maxOpenPreparedStatements", "-1");
            delegate = new DataSourceService(null, bean);
        } else {
            bean = new ResourceBean();
            bean.setId(SystemServiceId.SYS_ENTITY_DS);
            bean.setDescription(I18N.getLabel("easyplatform.sys.cl.desp"));
            bean.setName(I18N.getLabel("easyplatform.sys.cl.name"));
            bean.setType(EntityType.DATASOURCE.getName());
            bean.setProps(new HashMap<String, String>());
            Iterator<Map.Entry<String, String>> itr = section.entrySet()
                    .iterator();
            while (itr.hasNext()) {
                Map.Entry<String, String> entry = itr.next();
                if (!Strings.isBlank(entry.getValue())) {
                    bean.getProps().put(entry.getKey(), entry.getValue());
                }
            }
            delegate = new DataSourceService(null, bean);
        }
        delegate.setEngineConfiguration(engineConfiguration);
        delegate.start();
        setState(StateType.START);
        //创建参数表
        EntityInfo e = new EntityInfo();
        e.setId(SystemServiceId.SYS_ENTITY_DS);
        e.setStatus('D');
        EntityDao dao = DaoFactory.createEntityDao(this);
        dao.updateModel(e);
        StringBuilder sb = new StringBuilder();
        StringOutputStream os = new StringOutputStream(sb);
        TransformerFactory.newInstance().transformToXml(bean, os);
        e.setId(bean.getId());
        e.setName(bean.getName());
        e.setDescription(bean.getDescription());
        e.setContent(sb.toString());
        e.setType(bean.getType());
        e.setCreateUser("system");
        e.setStatus('C');
        dao.updateModel(e);
    }

    @Override
    public void stop() throws ServiceException {
        if (getState() != StateType.STOP) {
            delegate.stop();
            setState(StateType.STOP);
        }
    }

    @Override
    public Map<String, Object> getRuntimeInfo() {
        return delegate.getRuntimeInfo();
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.sql.CommonDataSource#getLogWriter()
     */
    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return delegate.getLogWriter();
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter)
     */
    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
        delegate.setLogWriter(out);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.sql.CommonDataSource#setLoginTimeout(int)
     */
    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
        delegate.setLoginTimeout(seconds);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.sql.CommonDataSource#getLoginTimeout()
     */
    @Override
    public int getLoginTimeout() throws SQLException {
        return delegate.getLoginTimeout();
    }

    /*
     * (non-Javadoc)
     *
     * @see java.sql.Wrapper#unwrap(java.lang.Class)
     */
    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return delegate.unwrap(iface);
    }

    /*
     * (non-Javadoc)
     *
     * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
     */
    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return delegate.isWrapperFor(iface);
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.sql.DataSource#getConnection()
     */
    @Override
    public Connection getConnection() throws SQLException {
        return delegate.getConnection();
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.sql.DataSource#getConnection(java.lang.String,
     * java.lang.String)
     */
    @Override
    public Connection getConnection(String username, String password)
            throws SQLException {
        return delegate.getConnection(username, password);
    }

    @Override
    public Date getStartTime() {
        return delegate.getStartTime();
    }

    @Override
    public String toString() {
        return delegate.toString();
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return delegate.getParentLogger();
    }

    @Override
    public ResourceBean getEntity() {
        return delegate.getEntity();
    }

    @Override
    public void resetSqlStat(Long id) {
        delegate.resetSqlStat(id);
    }

    @Override
    public void resetDataSourceStat() {
        delegate.resetDataSourceStat();
    }
}
